package com.lst.tools.redis.service.impl;

import com.lst.tools.basics.function.NoneParamFunction;
import com.lst.tools.redis.constant.RedissonConstants;
import com.lst.tools.redis.service.IRedissonService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author: Frank
 * @date: 2019/09/24 13:51
 * @version: V1.0
 */
@Service
public class RedissonService implements IRedissonService {

    private static final Logger LOGGER = LoggerFactory.getLogger(RedissonService.class);

    /**
     * 需要使用到的时候才注入
     */
    @Autowired(required = false)
    private RedissonClient redissonClient;

    /**
     * 分布式锁包裹方法
     *
     * @param lockName  锁名字
     * @param waitTime  阻塞等待时长   单位：秒
     * @param leaseTime 自动解锁时间   单位：秒
     * @param fun       处理逻辑
     */
    @Override
    public <T> T tryLockExecute(String lockName, int waitTime, int leaseTime, NoneParamFunction<T> fun) {
        RLock lock = redissonClient.getLock(RedissonConstants.LOCK_TITLE_PREFIX_ + lockName);
        try {
            if (lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS)) {
                return fun.callback();
            }
        } catch (InterruptedException e) {
            LOGGER.error("lockName:{[]} tryLock error", lockName);
        } finally {
            try {
                if (lock != null && lock.isLocked()) {
                    lock.unlock();
                }
            } catch (Exception e) {
                //超过waitTime还没有获取到锁时，就会return，调用unlock方法，会报错。因为不是它的锁，解锁会抛异常
                return null;
            }
        }
        return null;
    }
}
